<template>
	<div class="chat-view-container">
		<!-- header -->
		<div class="chat-view-header">
			<span>浏览器AI助手</span>
			<SvgSliders class="setting" @click="handleSettingClick"></SvgSliders>
		</div>

		<!-- 聊天列表 -->
		<div class="chat-list-container" ref="chatListContainerRef">
			<div class="chat-list" v-if="chatList.length > 0">
				<div
					class="chat-list-item"
					v-for="(item, index) in chatList"
					:key="'chat-list-item' + index"
				>
					<div class="user" v-if="item.role === 'user'">
						<div class="info">
							<div class="name">{{ item.name }}</div>
							<div class="time">{{ item.createTime }}</div>
							<div class="content">{{ item.content }}</div>
						</div>
						<div class="avatar">
							<img :src="item.avatar" alt="" />
						</div>
					</div>

					<div class="assistant" v-else>
						<div class="avatar">
							<img :src="item.avatar" alt="" />
						</div>
						<div class="info">
							<div class="name">{{ item.name }}</div>
							<div class="time">{{ item.createTime }}</div>
							<!-- <div class="content">{{ item.content }}</div> -->
							<McMarkdownCard
								:content="item.content"
								:enable-think="true"
							></McMarkdownCard>
						</div>
					</div>
				</div>
			</div>
			<div class="chat-list-empty" v-else>嗨，请问有什么可以帮助您的吗?</div>
		</div>
		<!-- 输入框容器 -->
		<div class="chat-input-container">
			<!-- 操作按钮 -->
			<div class="chat-operate">
				<select v-model="curAssistant" class="select-assist">
					<option
						v-for="item in assistants"
						:value="item.value"
						:key="item.value"
					>
						{{ item.name }}
					</option>
				</select>
				<div class="buttons">
					<button class="button">图片</button>
					<button class="button">文件</button>
					<button class="button">历史</button>
					<button class="button">新话题</button>
				</div>
			</div>
			<!-- 输入框 -->
			<div class="input-container">
				<textarea
					class="textarea"
					placeholder="Type your message here..."
					v-model="inputValue"
					@keydown.enter="handleInputEnter"
				></textarea>
				<div class="input-operate">
					<select
						v-model="curModel"
						class="select-model"
						@change="handleModelChange"
					>
						<option
							v-for="(item, index) in models"
							:value="index"
							:key="item.id + index"
						>
							{{ item.name + " - " + item.provider }}
						</option>
					</select>
					<button
						class="send-button"
						@click="handleSend"
						:disabled="sendBtnDisabled"
					>
						↑
					</button>
				</div>
			</div>
		</div>
		<!-- 供应商配置弹窗 -->
		<ProviderConfigModal
			v-model:visible="showProviderConfig"
			@save="handleProviderSave"
		/>
	</div>
</template>

<script setup lang="ts">
import { ref, nextTick, computed, watch, onMounted, onUnmounted } from "vue";

import { McMarkdownCard } from "@matechat/core";
import ProviderConfigModal from "./ProviderConfigModal.vue";
import SvgSliders from "../assets/sliders.svg";
import DefaultAvatar from "../assets/icon.png";
import type { Model } from "../AiCore/AiCore";
import { useAiCore } from "../AiCore/index";
import { useChatStore } from "../store/chat";
const aiCore = useAiCore();
const chatStore = useChatStore();

onMounted(async () => {
	await aiCore.loadProviders();
	initData();
	addObserver();
});

onUnmounted(() => {
	// 清理MutationObserver
	removeObserver();
});

interface ChatItem {
	id: string;
	role: "user" | "assistant";
	avatar: string;
	name: string;
	content: string;
	model?: string;
	assistant?: string;
	status?: "loading" | "success" | "error";
	createTime: string;
	endTime?: string;
}

watch(
	() => chatStore.fromContent,
	(newVal) => {
		if (newVal) {
			inputValue.value = newVal;
		}
	}
);

const showProviderConfig = ref(false);
const chatList = ref<ChatItem[]>([]);
const inputValue = ref("");
const isChating = ref(false);

// 选择 - 助手
const curAssistant = ref("default");
const assistants = ref([
	{
		name: "默认助手",
		value: "default",
		cueWord:
			"你是一位热情的行业专家（根据对话场景确定领域），你非常健谈，说话幽默风趣，引人入胜。",
	},
]);

// 选择 - 模型
const curModel = ref(0);
const models = ref<Model[]>([]);
const handleModelChange = () => {
	// 切换模型
	aiCore.setCurrentModel(models.value[curModel.value]);
};

// 初始化数据
const initData = async () => {
	models.value = await aiCore.enabledModels;
};

// 列表容器
const chatListContainerRef = ref<HTMLElement | null>(null);

// 供应商 - 设置
const handleSettingClick = () => {
	showProviderConfig.value = true;
};

const handleProviderSave = () => {
	initData();
};

const sendBtnDisabled = computed(() => {
	return !inputValue.value.trim() || isChating.value;
});

const handleInputEnter = (e: KeyboardEvent) => {
	// 阻止默认的换行行为
	e.preventDefault();
	if (e.ctrlKey && e.key == "Enter") {
		inputValue.value += "\n";
		return;
	}
	// 如果按下的是回车键且没有按下Shift键，则发送消息
	if (e.key === "Enter" && !e.shiftKey) {
		handleSend();
	}
};
const handleSend = async () => {
	if (!inputValue.value.trim() || isChating.value) return;
	const content = inputValue.value.trim();

	const userMessage: ChatItem = {
		id: createId(),
		role: "user",
		avatar: DefaultAvatar,
		name: "我",
		content: content,
		createTime: new Date().toLocaleString(),
	};

	chatList.value.push(userMessage);
	inputValue.value = "";
	isChating.value = true;

	chatList.value.push({
		id: createId(),
		role: "assistant",
		avatar: aiCore.currentProviderIcon,
		name: aiCore.currentProvider?.name + " - " + aiCore.currentModel?.name,
		content: "",
		status: "success",
		createTime: new Date().toLocaleString(),
	});

	// 等待DOM更新完成并立即滚动到底部
	await nextTick();
	scrollToBottom();

	const aiMessage = chatList.value[chatList.value.length - 1];

	await aiCore.sendChat({
		content: userMessage.content,
		stream: true,
		onMessage: (content) => {
			if (content) {
				aiMessage.content = content;
			}
		},
		onFinish: () => {
			isChating.value = false;
		},
		onError: (error) => {
			aiMessage.content = `错误: ${
				error instanceof Error ? error.message : "未知错误"
			}`;
			isChating.value = false;
		},
	});
};
/**
 * 生成一个八位数ID
 */
const createId = () => {
	return Date.now().toString().slice(-8) + Math.random().toString(10).slice(-8);
};

/**
 * 滚动到聊天列表底部
 */
const scrollToBottom = () => {
	if (chatListContainerRef.value) {
		chatListContainerRef.value.scrollTop =
			chatListContainerRef.value.scrollHeight;
	}
};
let scrollObserver: MutationObserver | null = null;
// 添加监听
const addObserver = () => {
	// 监听chatListContainerRef的内容变化，以检测scrollHeight变化
	if (chatListContainerRef.value) {
		let lastScrollHeight = chatListContainerRef.value.scrollHeight;

		// 创建MutationObserver来监听子节点变化
		const mutationObserver = new MutationObserver(() => {
			// 使用nextTick确保DOM更新完成
			nextTick(() => {
				if (chatListContainerRef.value) {
					const currentScrollHeight = chatListContainerRef.value.scrollHeight;

					// 只有当scrollHeight真正发生变化时才滚动
					if (currentScrollHeight !== lastScrollHeight) {
						lastScrollHeight = currentScrollHeight;

						// 如果正在聊天中，自动滚动到底部
						if (isChating.value) {
							scrollToBottom();
						}
					}
				}
			});
		});

		// 配置观察选项：监听子节点变化和子树变化
		const config = {
			childList: true,
			subtree: true,
			characterData: true,
		};

		mutationObserver.observe(chatListContainerRef.value, config);

		// 将observer存储起来，用于卸载时清理
		scrollObserver = mutationObserver;
	}
};
const removeObserver = () => {
	if (scrollObserver) {
		scrollObserver.disconnect();
		scrollObserver = null;
	}
};
</script>

<style scoped lang="scss">
.chat-view-container {
	height: 100%;
	width: 100%;
	display: flex;
	flex-direction: column;
	flex-wrap: nowrap;
	background-color: var(--color-background);
	// 头部
	.chat-view-header {
		position: relative;
		width: 100%;
		height: 40px;
		box-shadow: 0 1px 4px 0 var(--color-border);
		text-align: center;
		font-size: 18px;
		font-weight: bold;
		line-height: 40px;
		.setting {
			cursor: pointer;
			position: absolute;
			right: 16px;
			top: 50%;
			transform: translateY(-50%);
			height: 20px;
			width: 20px;
			fill: var(--color-primary);
		}
	}

	// 聊天列表容器
	.chat-list-container {
		width: 100%;
		flex: 1 1 auto;
		height: auto;
		overflow-y: auto;
		padding: 8px 16px 8px;
		// 聊天列表
		.chat-list {
			width: 100%;
			.chat-list-item {
				width: 100%;
				// 用户样式
				.user {
					width: 100%;
					display: flex;
					flex-direction: row;
					flex-wrap: nowrap;
					align-items: flex-start;
					justify-content: flex-end;
					padding: 0 0 0 40px;
					gap: 8px;
					.info {
						flex: 1 1 auto;
						display: flex;
						flex-direction: column;
						flex-wrap: nowrap;
						align-items: flex-end;
						justify-content: flex-start;
						overflow: hidden;
						.name {
							font-size: 18px;
							font-weight: 550;
						}
						.time {
							font-size: 12px;
							color: var(--color-text-secondary);
						}
						.content {
							font-size: 16px;
						}
					}
				}
				// 助手样式
				.assistant {
					width: 100%;
					display: flex;
					flex-direction: row;
					flex-wrap: nowrap;
					align-items: flex-start;
					justify-content: flex-start;
					padding: 0 40px 0 0;
					gap: 8px;
					.info {
						flex: 1 1 auto;
						display: flex;
						flex-direction: column;
						flex-wrap: nowrap;
						align-items: flex-start;
						justify-content: flex-start;
						.name {
							font-size: 18px;
							font-weight: 550;
						}
						.time {
							font-size: 12px;
							color: var(--color-text-secondary);
						}
						.content {
							font-size: 16px;
							max-width: 100%;
							word-wrap: break-word;
							overflow-wrap: break-word;
						}
					}
				}
				.avatar {
					flex: 0 0 34px;
					width: 34px;
					height: 34px;
					border-radius: 50%;
					overflow: hidden;
					img {
						width: 100%;
						height: 100%;
						object-fit: cover;
					}
				}
			}
			// 空白提示
		}
		.chat-list-empty {
			height: 100%;
			font-size: 35px;
			color: var(--color-text);
			font-weight: bold;
			text-align: center;
			display: flex;
			align-items: center;
			justify-content: center;
		}
	}

	// 输入框容器
	.chat-input-container {
		width: 100%;
		flex: 0 0 auto;
		display: flex;
		flex-direction: column;
		flex-wrap: nowrap;
		padding: 0px 16px 16px;
		.chat-operate {
			height: 30px;
			width: 100%;
			display: flex;
			flex-direction: row;
			flex-wrap: nowrap;
			align-items: center;
			justify-content: space-between;
			.select-assist {
				border: none;
				background-color: transparent;
				&:focus-visible {
					outline: none;
				}
			}
			.buttons {
				display: flex;
				flex-direction: row;
				flex-wrap: nowrap;
				align-items: center;
				justify-content: flex-end;
				.button {
					cursor: pointer;
					color: var(--color-primary);
					font-size: 14px;
					border: none;
					background: transparent;
				}
			}
		}
		.input-container {
			width: 100%;
			border: 1px solid var(--color-border);
			border-radius: 8px;
			padding: 12px 12px 5px;
			.textarea {
				width: 100%;
				height: 80px;
				border: none;
				resize: none;
				outline: none;
				font-size: 16px;
				color: var(--color-text);
				background-color: transparent;
				&:focus-visible {
					outline: none;
				}
			}
			.input-operate {
				width: 100%;
				height: 30px;
				display: flex;
				flex-direction: row;
				flex-wrap: nowrap;
				align-items: center;
				justify-content: space-between;
				.select-model {
					border: none;
					background-color: transparent;
					color: var(--color-text);
					font-size: 14px;
					&:focus-visible {
						outline: none;
					}
				}
				.send-button {
					cursor: pointer;
					background-color: var(--color-primary);
					color: white;
					font-size: 14px;
					border: none;
					height: 25px;
					width: 25px;
					font-weight: bold;
					border-radius: 50%;
					display: flex;
					align-items: center;
					justify-content: center;
					&:disabled {
						cursor: not-allowed;
						background-color: var(--color-border);
					}
				}
			}
		}
	}
}
</style>
